"""
日历组件

这是一个功能完善的日程管理系统，提供：
- 日程基础管理（创建、编辑、删除、查看）
- 重复日程功能（每日、每周、每月、每年重复）
- 提醒和通知（弹窗、邮件、短信）
- 日程分类和标签
- 协作功能（分享、权限控制、参与者管理）
- 时间管理（时区、冲突检测、智能安排）
- 数据导入导出和统计分析

参考Google Calendar、Microsoft Outlook Calendar等商业化日程工具设计。
"""

from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from typing import List, Optional
from datetime import datetime, timedelta
import uuid

from db.session import get_db
from services.permission import require_permission, get_permission_service, PermissionCodes
from .models import (
    Calendar, Event, EventRecurrence, EventReminder, 
    EventParticipant, EventTag, CalendarShare, EventComment
)
from .schemas import (
    CalendarCreate, CalendarUpdate, CalendarResponse,
    EventCreate, EventUpdate, EventResponse,
    EventRecurrenceCreate, EventRecurrenceUpdate, EventRecurrenceResponse,
    EventReminderCreate, EventReminderUpdate, EventReminderResponse,
    EventParticipantCreate, EventParticipantUpdate, EventParticipantResponse,
    CalendarShareCreate, CalendarShareUpdate, CalendarShareResponse,
    EventTagCreate, EventTagUpdate, EventTagResponse,
    EventCommentCreate, EventCommentUpdate, EventCommentResponse,
    EventSearchRequest, EventSearchResponse
)
from .services import CalendarService, EventService, RecurrenceService, ReminderService, ShareService

# 创建路由
router = APIRouter(prefix="/calendar", tags=["日历组件"])

# 创建服务实例
calendar_service = CalendarService()
event_service = EventService()
recurrence_service = RecurrenceService()
reminder_service = ReminderService()
share_service = ShareService()

# 导出模型（用于动态加载）
models = [
    Calendar, Event, EventRecurrence, EventReminder,
    EventParticipant, EventTag, CalendarShare, EventComment
]

# 导出路由和模型
__all__ = ["router", "models"]


# ===== 日历管理 API =====

@router.post("/calendars", response_model=CalendarResponse, summary="创建日历")
async def create_calendar(
    calendar: CalendarCreate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    创建新的日历
    
    创建一个个人日历，可以设置名称、描述、颜色等属性
    """
    return await calendar_service.create_calendar(db, calendar, current_user_id)


@router.get("/calendars", response_model=List[CalendarResponse], summary="获取日历列表")
async def get_calendars(
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取用户的所有日历
    
    包括用户拥有的日历和被分享的日历
    """
    return await calendar_service.get_user_calendars(db, current_user_id)


@router.get("/calendars/{calendar_id}", response_model=CalendarResponse, summary="获取日历详情")
async def get_calendar(
    calendar_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取指定日历的详细信息
    
    需要用户有访问该日历的权限
    """
    calendar = await calendar_service.get_calendar(db, calendar_id, current_user_id)
    if not calendar:
        raise HTTPException(status_code=404, detail="日历不存在或无权访问")
    return calendar


@router.put("/calendars/{calendar_id}", response_model=CalendarResponse, summary="更新日历")
async def update_calendar(
    calendar_id: int,
    calendar: CalendarUpdate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    更新日历信息
    
    可以更新日历的名称、描述、颜色等属性
    """
    updated_calendar = await calendar_service.update_calendar(db, calendar_id, calendar, current_user_id)
    if not updated_calendar:
        raise HTTPException(status_code=404, detail="日历不存在或无权访问")
    return updated_calendar


@router.delete("/calendars/{calendar_id}", summary="删除日历")
async def delete_calendar(
    calendar_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    删除日历
    
    只能删除自己拥有的日历
    """
    success = await calendar_service.delete_calendar(db, calendar_id, current_user_id)
    if not success:
        raise HTTPException(status_code=404, detail="日历不存在或无权删除")
    return {"message": "日历删除成功"}


# ===== 日程管理 API =====

@router.post("/events", response_model=EventResponse, summary="创建日程")
async def create_event(
    event: EventCreate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    创建新的日程
    
    可以设置日程的基本信息、标签、参与者、提醒等
    """
    return await event_service.create_event(db, event, current_user_id)


@router.get("/events/{event_id}", response_model=EventResponse, summary="获取日程详情")
async def get_event(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取指定日程的详细信息
    
    包括日程的基本信息、标签、参与者、提醒、重复规则等
    """
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    return event


@router.get("/calendars/{calendar_id}/events", response_model=List[EventResponse], summary="获取日历下的日程")
async def get_calendar_events(
    calendar_id: int,
    start_date: Optional[datetime] = Query(None, description="开始日期"),
    end_date: Optional[datetime] = Query(None, description="结束日期"),
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取指定日历下的所有日程
    
    可以按时间范围过滤
    """
    events = await event_service.get_events_by_calendar(db, calendar_id, current_user_id)
    
    # 按时间范围过滤
    if start_date:
        events = [event for event in events if event.start_time >= start_date]
    if end_date:
        events = [event for event in events if event.end_time <= end_date]
    
    return events


@router.put("/events/{event_id}", response_model=EventResponse, summary="更新日程")
async def update_event(
    event_id: int,
    event: EventUpdate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    更新日程信息
    
    可以更新日程的基本信息、标签等
    """
    updated_event = await event_service.update_event(db, event_id, event, current_user_id)
    if not updated_event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    return updated_event


@router.delete("/events/{event_id}", summary="删除日程")
async def delete_event(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    删除日程
    
    只能删除自己创建或有管理权限的日程
    """
    success = await event_service.delete_event(db, event_id, current_user_id)
    if not success:
        raise HTTPException(status_code=404, detail="日程不存在或无权删除")
    return {"message": "日程删除成功"}


@router.post("/events/search", response_model=EventSearchResponse, summary="搜索日程")
async def search_events(
    search: EventSearchRequest,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    搜索日程
    
    支持按关键词、时间范围、日历、标签等多种条件搜索
    """
    return await event_service.search_events(db, search, current_user_id)


# ===== 重复规则 API =====

@router.post("/events/{event_id}/recurrence", response_model=EventRecurrenceResponse, summary="设置重复规则")
async def create_recurrence(
    event_id: int,
    recurrence: EventRecurrenceCreate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    为日程设置重复规则
    
    支持每日、每周、每月、每年等多种重复模式
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    return await recurrence_service.create_recurrence(db, event_id, recurrence)


@router.get("/events/{event_id}/recurrence", response_model=EventRecurrenceResponse, summary="获取重复规则")
async def get_recurrence(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取日程的重复规则
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    recurrence = await recurrence_service.get_recurrence(db, event_id)
    if not recurrence:
        raise HTTPException(status_code=404, detail="重复规则不存在")
    return recurrence


@router.put("/events/{event_id}/recurrence", response_model=EventRecurrenceResponse, summary="更新重复规则")
async def update_recurrence(
    event_id: int,
    recurrence: EventRecurrenceUpdate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    更新日程的重复规则
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    updated_recurrence = await recurrence_service.update_recurrence(db, event_id, recurrence)
    if not updated_recurrence:
        raise HTTPException(status_code=404, detail="重复规则不存在")
    return updated_recurrence


@router.delete("/events/{event_id}/recurrence", summary="删除重复规则")
async def delete_recurrence(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    删除日程的重复规则
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    success = await recurrence_service.delete_recurrence(db, event_id)
    if not success:
        raise HTTPException(status_code=404, detail="重复规则不存在")
    return {"message": "重复规则删除成功"}


@router.get("/events/{event_id}/recurrence/instances", summary="获取重复日程实例")
async def get_recurring_instances(
    event_id: int,
    start_date: datetime = Query(..., description="开始日期"),
    end_date: datetime = Query(..., description="结束日期"),
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取重复日程在指定时间范围内的所有实例
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    instances = await recurrence_service.generate_recurring_events(db, event_id, start_date, end_date)
    return {"instances": instances}


# ===== 提醒管理 API =====

@router.post("/events/{event_id}/reminders", response_model=EventReminderResponse, summary="添加提醒")
async def create_reminder(
    event_id: int,
    reminder: EventReminderCreate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    为日程添加提醒
    
    支持弹窗、邮件、短信等多种提醒方式
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    return await reminder_service.create_reminder(db, event_id, reminder)


@router.get("/events/{event_id}/reminders", response_model=List[EventReminderResponse], summary="获取提醒列表")
async def get_reminders(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取日程的所有提醒设置
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    return await reminder_service.get_reminders(db, event_id)


@router.put("/reminders/{reminder_id}", response_model=EventReminderResponse, summary="更新提醒")
async def update_reminder(
    reminder_id: int,
    reminder: EventReminderUpdate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    更新提醒设置
    """
    updated_reminder = await reminder_service.update_reminder(db, reminder_id, reminder)
    if not updated_reminder:
        raise HTTPException(status_code=404, detail="提醒不存在")
    return updated_reminder


@router.delete("/reminders/{reminder_id}", summary="删除提醒")
async def delete_reminder(
    reminder_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    删除提醒
    """
    success = await reminder_service.delete_reminder(db, reminder_id)
    if not success:
        raise HTTPException(status_code=404, detail="提醒不存在")
    return {"message": "提醒删除成功"}


@router.get("/reminders/pending", response_model=List[EventReminderResponse], summary="获取待发送提醒")
async def get_pending_reminders(
    current_time: datetime = Query(default_factory=datetime.utcnow, description="当前时间"),
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取所有待发送的提醒
    
    用于定时任务处理提醒发送
    """
    return await reminder_service.get_pending_reminders(db, current_time)


# ===== 日程分享 API =====

@router.post("/calendars/{calendar_id}/share", response_model=CalendarShareResponse, summary="分享日历")
async def share_calendar(
    calendar_id: int,
    share: CalendarShareCreate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    分享日历给其他用户
    
    可以设置查看、编辑、管理等权限级别
    """
    return await share_service.share_calendar(db, calendar_id, share, current_user_id)


@router.get("/calendars/{calendar_id}/shares", response_model=List[CalendarShareResponse], summary="获取日历分享列表")
async def get_calendar_shares(
    calendar_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取日历的所有分享记录
    """
    return await share_service.get_calendar_shares(db, calendar_id, current_user_id)


@router.put("/shares/{share_id}", response_model=CalendarShareResponse, summary="更新分享权限")
async def update_share(
    share_id: int,
    share: CalendarShareUpdate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    更新日历分享的权限设置
    """
    updated_share = await share_service.update_share(db, share_id, share, current_user_id)
    if not updated_share:
        raise HTTPException(status_code=404, detail="分享记录不存在或无权访问")
    return updated_share


@router.delete("/shares/{share_id}", summary="撤销分享")
async def revoke_share(
    share_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    撤销日历分享
    """
    success = await share_service.revoke_share(db, share_id, current_user_id)
    if not success:
        raise HTTPException(status_code=404, detail="分享记录不存在或无权访问")
    return {"message": "分享已撤销"}


@router.post("/shares/{share_id}/accept", summary="接受分享")
async def accept_share(
    share_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    接受日历分享邀请
    """
    success = await share_service.accept_share(db, share_id, current_user_id)
    if not success:
        raise HTTPException(status_code=404, detail="分享邀请不存在或无权访问")
    return {"message": "分享已接受"}


# ===== 参与者管理 API =====

@router.post("/events/{event_id}/participants", response_model=EventParticipantResponse, summary="添加参与者")
async def add_participant(
    event_id: int,
    participant: EventParticipantCreate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    为日程添加参与者
    
    可以设置参与者的权限和通知偏好
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    # 这里应该调用EventService中的添加参与者方法
    # 为了简化，直接创建参与者
    db_participant = EventParticipant(
        event_id=event_id,
        **participant.dict()
    )
    db.add(db_participant)
    await db.commit()
    await db.refresh(db_participant)
    return db_participant


@router.get("/events/{event_id}/participants", response_model=List[EventParticipantResponse], summary="获取参与者列表")
async def get_participants(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取日程的所有参与者
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    query = select(EventParticipant).where(EventParticipant.event_id == event_id)
    result = await db.execute(query)
    return result.scalars().all()


@router.put("/participants/{participant_id}", response_model=EventParticipantResponse, summary="更新参与者状态")
async def update_participant(
    participant_id: int,
    participant: EventParticipantUpdate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    更新参与者的状态和权限
    """
    query = select(EventParticipant).where(EventParticipant.id == participant_id)
    result = await db.execute(query)
    db_participant = result.scalar_one_or_none()
    
    if not db_participant:
        raise HTTPException(status_code=404, detail="参与者不存在")
    
    # 检查权限
    if db_participant.user_id != current_user_id:
        event = await event_service.get_event(db, db_participant.event_id, current_user_id)
        if not event:
            raise HTTPException(status_code=404, detail="无权访问此日程")
    
    # 更新数据
    update_data = participant.dict(exclude_unset=True)
    for field, value in update_data.items():
        setattr(db_participant, field, value)
    
    if participant.status:
        db_participant.responded_at = datetime.utcnow()
    
    await db.commit()
    await db.refresh(db_participant)
    return db_participant


@router.delete("/participants/{participant_id}", summary="移除参与者")
async def remove_participant(
    participant_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    移除日程参与者
    """
    query = select(EventParticipant).where(EventParticipant.id == participant_id)
    result = await db.execute(query)
    db_participant = result.scalar_one_or_none()
    
    if not db_participant:
        raise HTTPException(status_code=404, detail="参与者不存在")
    
    # 检查权限
    event = await event_service.get_event(db, db_participant.event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="无权访问此日程")
    
    await db.delete(db_participant)
    await db.commit()
    return {"message": "参与者已移除"}


# ===== 标签管理 API =====

@router.post("/tags", response_model=EventTagResponse, summary="创建标签")
async def create_tag(
    tag: EventTagCreate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    创建新的标签
    
    用于对日程进行分类管理
    """
    db_tag = EventTag(
        **tag.dict(),
        user_id=current_user_id
    )
    db.add(db_tag)
    await db.commit()
    await db.refresh(db_tag)
    return db_tag


@router.get("/tags", response_model=List[EventTagResponse], summary="获取标签列表")
async def get_tags(
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取用户的所有标签
    """
    query = select(EventTag).where(EventTag.user_id == current_user_id)
    result = await db.execute(query)
    return result.scalars().all()


@router.put("/tags/{tag_id}", response_model=EventTagResponse, summary="更新标签")
async def update_tag(
    tag_id: int,
    tag: EventTagUpdate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    更新标签信息
    """
    query = select(EventTag).where(EventTag.id == tag_id)
    result = await db.execute(query)
    db_tag = result.scalar_one_or_none()
    
    if not db_tag or db_tag.user_id != current_user_id:
        raise HTTPException(status_code=404, detail="标签不存在或无权访问")
    
    # 更新数据
    update_data = tag.dict(exclude_unset=True)
    for field, value in update_data.items():
        setattr(db_tag, field, value)
    
    await db.commit()
    await db.refresh(db_tag)
    return db_tag


@router.delete("/tags/{tag_id}", summary="删除标签")
async def delete_tag(
    tag_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    删除标签
    """
    query = select(EventTag).where(EventTag.id == tag_id)
    result = await db.execute(query)
    db_tag = result.scalar_one_or_none()
    
    if not db_tag or db_tag.user_id != current_user_id:
        raise HTTPException(status_code=404, detail="标签不存在或无权访问")
    
    await db.delete(db_tag)
    await db.commit()
    return {"message": "标签删除成功"}


# ===== 日程评论 API =====

@router.post("/events/{event_id}/comments", response_model=EventCommentResponse, summary="添加评论")
async def add_comment(
    event_id: int,
    comment: EventCommentCreate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    为日程添加评论
    
    支持回复评论和添加附件
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    db_comment = EventComment(
        event_id=event_id,
        user_id=current_user_id,
        **comment.dict()
    )
    db.add(db_comment)
    await db.commit()
    await db.refresh(db_comment)
    return db_comment


@router.get("/events/{event_id}/comments", response_model=List[EventCommentResponse], summary="获取评论列表")
async def get_comments(
    event_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    获取日程的所有评论
    """
    # 检查日程权限
    event = await event_service.get_event(db, event_id, current_user_id)
    if not event:
        raise HTTPException(status_code=404, detail="日程不存在或无权访问")
    
    query = select(EventComment).where(EventComment.event_id == event_id)
    result = await db.execute(query)
    return result.scalars().all()


@router.put("/comments/{comment_id}", response_model=EventCommentResponse, summary="更新评论")
async def update_comment(
    comment_id: int,
    comment: EventCommentUpdate,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    更新评论内容
    """
    query = select(EventComment).where(EventComment.id == comment_id)
    result = await db.execute(query)
    db_comment = result.scalar_one_or_none()
    
    if not db_comment or db_comment.user_id != current_user_id:
        raise HTTPException(status_code=404, detail="评论不存在或无权访问")
    
    # 更新数据
    update_data = comment.dict(exclude_unset=True)
    for field, value in update_data.items():
        setattr(db_comment, field, value)
    
    await db.commit()
    await db.refresh(db_comment)
    return db_comment


@router.delete("/comments/{comment_id}", summary="删除评论")
async def delete_comment(
    comment_id: int,
    db: AsyncSession = Depends(get_db),
    current_user_id: int = 1  # 这里应该从认证中间件获取
):
    """
    删除评论
    """
    query = select(EventComment).where(EventComment.id == comment_id)
    result = await db.execute(query)
    db_comment = result.scalar_one_or_none()
    
    if not db_comment or db_comment.user_id != current_user_id:
        raise HTTPException(status_code=404, detail="评论不存在或无权访问")
    
    await db.delete(db_comment)
    await db.commit()
    return {"message": "评论删除成功"}